# coding: utf-8
# author: t_wolf

from web_utils import *

"""
# 所有filter接收的首个入参都为worker对象
# 通过首个框架类对象可以获取到四个属性
#  header: 可以取到请求头中的键值, obj.header.get("xx")
# session: 可以取到用户session并做操作, obj.session.get("xx") || obj.session.set_default(key, value)
# request: 可以取到请求中的参数字典, obj.request.get("xx")
#   pages: 获取当前可以渲染的页面对象, pages.works.index
#
# post_filter:
# 接收参数比pre_filter多了一个之前步骤的返回值
# 实例:
# def example(worker, arg_list, last_arg):
#     print last_arg
#
"""


class PostFilter:
    def __init__(self):
        pass

    @staticmethod
    @post_filter
    def header_redirect(worker, redirect_options, last_result):
        """
        返回重定向
        :param worker: frame_worker对象
        :param redirect_options: 重定向参数字典, url为重定向的url, time为重定向等待时间
        :param last_result: 上一个返回值
        :return: 返回的响应中携带重定向内容
        """
        redirect_options = {} if redirect_options is None else redirect_options
        _url = redirect_options['url'] if 'url' in redirect_options else web.ctx.env.get('HTTP_REFERER', '/')
        _time = redirect_options['time'] if 'time' in redirect_options else 0

        logger.debug("Redirect pages to [%s] in [%s] seconds." % (_url, _time))

        web.header('Content-Type', 'text/html')
        web.header('Refresh', '%d;url="%s"' % (_time, _url))
        return last_result

    @staticmethod
    @post_filter
    def result_to_json(worker, encoded, last_result):
        """
        返回值format为json
        :param worker: frame_worker对象
        :param encoded: json转码格式
        :param last_result: 上一个返回值
        :return: 返回处理后数据
        """
        logger.debug("Transfer return data to json format.")
        encoded = encoded if encoded else None
        web.header("Content-Type", "application/json")
        # 增加将返回值全部进行一次decode
        last_result = decode_object(last_result)
        return params2json(last_result, encoded)

    @staticmethod
    @post_filter
    def charset(worker, arg_list, last_result):
        """
        设置返回值编码格式
        :param worker: frame_worker对象
        :param arg_list: 编码类型
        :param last_result: 上一个返回值
        :return: 为Response加Header
        """
        worker.header_put("Content-Type", "Content-Type: text/html; charset=%s" % arg_list)
        return last_result

    @staticmethod
    @post_filter
    def return_to_file(worker, file_options, last_result):
        """
        设置返回结果以文件类型输出
        :param worker: frame_worker对象
        :param file_options: 参数字典, type, charset, name
        :param last_result: 上一个返回值
        :return: 为Response加Header, 作为文件下载
        """
        file_options = {} if file_options is None else file_options
        file_type = file_options.get('type', 'text/plain')
        file_code = file_options.get('charset', 'utf-8')
        file_name = file_options.get('name', 'simple.txt')

        if not last_result:
            yield last_result

        web.header("Content-Disposition", "attachment;filename=%s" % file_name)
        # 增加大文件判断, 每次返回500KB(524288), 1024KB(1048576)
        if isinstance(last_result, file):
            last_result.seek(0, 2)
            len_size = last_result.tell()
            last_result.seek(0)
        else:
            len_size = len(last_result)

        if len_size > 524288:
            web.header("Content-Type", "application/octet-stream;charset=%s" % file_code)
            s_file = last_result if isinstance(last_result, file) else StringIO.StringIO(last_result)
            while True:
                buff = s_file.read(524288)
                if buff:
                    yield buff
                else:
                    break
        else:
            buff = last_result.read() if isinstance(last_result, file) else last_result
            web.header("Content-Type", "%s;charset=%s" % (file_type, file_code))
            yield buff
